﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using IntraVision.Web;
using IntraVision.Web.Security;
using System.Text.RegularExpressions;
using Model;

[AllowedRole("IsAdmin")]
public class KBController : EntityListController<KBFolder,NotarialServiceDataContext>
{
    bool create = false;

    public void Tree()
    {
        LayoutPath = "~/views/layouts/page.haml";
        TemplatePath = "~/views/kb/tree.haml";
        RegisterScript("kb/treepage.js");
        RegisterStylesheet("kb/kb.css");
        RenderView();
    }

    public void TreeFrame()
    {
        LayoutPath = "none";
        TemplatePath = "~/views/kb/treeframe.haml";
        RenderView();
    }

    public void Node()
    {
        if (!string.IsNullOrEmpty(Request["nolayout"]))
        {
            LayoutPath = "none";
            TemplatePath = "~/views/kb/_node.haml";
        }
        else
        {
            LayoutPath = "~/views/layouts/popup.haml";
            if (String.IsNullOrEmpty(TemplatePath)) TemplatePath = "~/views/kb/_node.haml";

            RegisterScript("kb/tree.js");
            RegisterStylesheet("tree/tree.css");
        }

        int pid = 0;
        Int32.TryParse(Request["parentid"], out pid);

        using (var dc = new NotarialServiceDataContext())
        {
            var user = ViewData["user"] as User;
            ViewData["folders"] = (from f in dc.KBFolders where (pid == 0 && f.ParentId == null) || f.ParentId == pid select f);
            RenderView();
        }
    }

    public void List()
    {
        List("");
    }

    public void List(string folderid)
    {
        using (var dc = new NotarialServiceDataContext())
        {
            int fid = 0;
            if (!string.IsNullOrEmpty(folderid)) Int32.TryParse(folderid, out fid);

            if (fid > 0)
            {
                var folder = dc.KBFolders.Single(f => f.Id == fid);
                var path = new List<string>();
                while (folder != null)
                {
                    path.Add(folder.Name);
                    folder = folder.Parent;
                }
                path.Add("База знаний");
                path.Reverse();
                ViewData["foldertitle"] = string.Join(" &rarr; ", path.ToArray());
            }
            else ViewData["foldertitle"] = "База знаний";

            ViewData["folderid"] = fid;
            ViewData["folders"] = (from f in dc.KBFolders orderby f.SortOrder where f.ParentId == null select f).ToList();
            ViewData["documents"] = (from d in dc.KBDocuments where d.ParentId == fid orderby d.SortOrder descending select d).ToList();

            LayoutPath = "~/views/layouts/page.haml";
            TemplatePath = "~/views/kb/list.haml";
            RenderView();
        }
    }

    protected override void EntityLoaded(NotarialServiceDataContext dc, KBFolder entity)
    {
        ViewData["whitebg"] = true;
        LayoutPath = "~/views/layouts/popup.haml";

        if (entity.Id == 0 && !string.IsNullOrEmpty(Request["parentid"]))
            entity.ParentId = Convert.ToInt32(Request["parentid"]);       
    }

    protected override void BeforeSubmit(NotarialServiceDataContext dc, KBFolder entity)
    {
        create = (entity.Id == 0);

        if (!string.IsNullOrEmpty(Request["oldparentid"]))
            ViewData["oldparentid"] = Request["oldparentid"];
    }

    protected override void AfterSubmit(NotarialServiceDataContext dc, KBFolder entity)
    {
        Logger.WriteLog(dc, (create) ? LogOperationType.KbCreate : LogOperationType.KbChange, (Session["User"] as User).Id, null, null);
    }

    protected override void EntityDeleted(NotarialServiceDataContext dc, List<KBFolder> deleted)
    {
        foreach (var entity in deleted)
            Logger.WriteLog(dc, LogOperationType.KbDelete, (Session["User"] as User).Id, null, null);
    }

    public override void View(string entityid)
    {
        TemplatePath = "~/views/kb/view.haml";
        RegisterStylesheet("kbdocument/kb.css");

        if (!string.IsNullOrEmpty(Request["readonly"])) ViewData["readonly"] = true;
        base.View(entityid);
    }

    [AllowedRole("kbadmin")]
    public void Edit(string entityid)
    {
        base.View(entityid);
    }

    public void ViewDocument(string documentid)
    {
        using (var dc = new NotarialServiceDataContext())
        {
            int did = 0;
            if (!string.IsNullOrEmpty(documentid)) Int32.TryParse(documentid, out did);

            var document = dc.KBDocuments.Single(d => d.Id == did);
            ViewData["document"] = document;

            int fid = document.ParentId;
            ViewData["folderid"] = fid;
            ViewData["folders"] = (from f in dc.KBFolders orderby f.SortOrder where f.ParentId == null select f).ToList();

            LayoutPath = "~/views/layouts/page.haml";
            TemplatePath = "~/views/kb/view.haml";
            RenderView();
        }
    }

    public void Search()
    {
        string requestSearchString = "";
        if (!String.IsNullOrEmpty(Request["searchstring"]))
            requestSearchString = Request["searchstring"].Trim();
        if (requestSearchString.Length == 0) return;

        int selectedFolderId = 0;
        if (!String.IsNullOrEmpty(Request["selectedfolderid"]) && !String.IsNullOrEmpty(Request["searchwhere"]) && Request["searchwhere"] == "folder")
            Int32.TryParse(Request["selectedfolderid"], out selectedFolderId);

        string searchString = GetSearchString(requestSearchString, "AND"); 
        if (searchString.Length == 0) return;

        const int pageSize = 50;
        int pageCount = 1;
        int page;
        if (String.IsNullOrEmpty(Request["page"]) || !Int32.TryParse(Request["page"], out page)) 
            page = 1;

        using(var dc = new NotarialServiceDataContext())
        {
            IQueryable<KBDocument> searchQuery = GetSearchQuery(dc, searchString, selectedFolderId);
            int count = searchQuery.Count();
            if( count == 0 ) //поиск по AND не дал результатов
            {
                //ищем по OR
                searchString = GetSearchString(requestSearchString, "OR"); 
                if (searchString.Length == 0) return;
                searchQuery = GetSearchQuery(dc, searchString, selectedFolderId);
                count = searchQuery.Count();
            }
            ViewData["Count"] = count;

            if (count > pageSize) pageCount = (int)Math.Ceiling((double)count / pageSize);
            if (page > pageCount || page <= 0) page = 1;
            ViewData["Page"] = page;
            ViewData["PageCount"] = pageCount;
            ViewData["PageSize"] = pageSize;

            searchQuery = searchQuery.Skip((page - 1) * pageSize).Take(pageSize);
            ViewData["Documents"] = searchQuery.ToList();
            ViewData["CountOnPage"] = searchQuery.Count();
        }

        ViewData["searchstring"] = requestSearchString;
        ViewData["selectedfolderid"] = selectedFolderId;
        ViewData["whitebg"] = true;

        LayoutPath = "~/views/layouts/popup.haml";
        TemplatePath = "~/views/kb/searchresults.haml";
        RegisterStylesheet("kb/kb.css");
        RegisterScript("kb/kb.js");

        RenderView();
    }

    private IQueryable<KBDocument> GetSearchQuery(NotarialServiceDataContext dc, string searchString, int selectedFolderId)
    {
        string[] rootfolders = (from f in dc.KBFolders where f.ParentId == null select f.Id.ToString()).ToArray();

        IQueryable<KBDocument> searchQuery = (from fts in dc.uf_KBSearch(searchString)
                                              join d in dc.KBDocuments on fts.KEY equals d.Id
                                              join f in dc.KBFolders on d.ParentId equals f.Id
                                              where rootfolders.Contains(f.Path.Substring(0, f.Path.IndexOf('|')))
                                              orderby fts.RANK descending
                                              select d);
        if (selectedFolderId > 0)
        {
            var folder = dc.KBFolders.SingleOrDefault(f => f.Id == selectedFolderId);
            if (folder != null)
                searchQuery = (from fts in dc.uf_KBSearch(searchString)
                               join d in dc.KBDocuments on fts.KEY equals d.Id
                               join f in dc.KBFolders on d.ParentId equals f.Id
                               where f.Path.StartsWith(folder.Path) && rootfolders.Contains(f.Path.Substring(0, f.Path.IndexOf('|')))
                               orderby fts.RANK descending
                               select d);
        }

        return searchQuery;
    }

    private static string GetSearchString(string requestSearchString, string condition)
    {
        if (!new[] { "and", "or" }.Contains(condition.ToLower())) return "";

        string result = "";
        if (!(requestSearchString.StartsWith("\"") && requestSearchString.EndsWith("\"")))
        {
            string[] words = Regex.Replace(requestSearchString, @"\s+", " ").Split(' ');
            foreach (var word in words)
                result += result.Length == 0 ? "FORMSOF(INFLECTIONAL," + word + ")" : condition + " FORMSOF(INFLECTIONAL," + word + ")";
        }
        return result;
    }
}
